/*
 * ﻿Copyright (C) 2009-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.gwetons.client.logging;

import java.util.ArrayList;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayMixed;
import com.google.gwt.core.client.JsArrayString;
import com.newmainsoftech.gwetons.shared.logging.LoggerWrap;

/**
 * Provides the access means to logger for JSNI method of GWT client side class to adapt 
 * <code>LoggerWrap</code> framework.<br />   
 * The out-of-box implementation of {@link JsniLoggerWrap} interface.
 * 
 * @author <a href="mailto:artymt@gmail.com">Arata Y.</a>
 *
 */
public class JsniLoggerWrapImpl implements JsniLoggerWrap {
	private LoggerWrap loggerWrap = null;
		public LoggerWrap getLoggerWrap() {
			return loggerWrap;
		}
		public void setLoggerWrap( LoggerWrap loggerWrap) {
			this.loggerWrap = loggerWrap;
		}

	// about log method -----------------------------------------------------------------------
	public native JavaScriptObject getLogFunction() /*-{
		var loggerWrap = this.@com.newmainsoftech.gwetons.client.logging.JsniLoggerWrapImpl::getLoggerWrap()();
		var logFunction
		= function( levelObj, message) {
			if ( loggerWrap) {
				if ( typeof( levelObj) == "string") {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::log(Ljava/lang/String;Ljava/lang/String;)(
						levelObj, message);
				}
				else {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::log(Ljava/util/logging/Level;Ljava/lang/String;)(
						levelObj, message);
				}
			}
		};
		return logFunction;
	}-*/;
	// ----------------------------------------------------------------------------------------
		
	// about entering methods -----------------------------------------------------------------
	native String getType( JsArrayMixed params, int index) /*-{
		return typeof( params[ index]);
	}-*/;
		
	public void entering( String sourceMethod, JsArrayMixed params) {
		LoggerWrap thisLoggerWrap = getLoggerWrap();
			if ( thisLoggerWrap == null) return;
		
		ArrayList<Object>  paramsArrayList = new ArrayList<Object>();
		if ( params != null) {
			for( int paramsIndex = 0; paramsIndex < params.length(); paramsIndex++) {
				String typeStr = getType( params, paramsIndex);
				if ( "undefined".equals( typeStr)) {
					paramsArrayList.add( null);
				}
				else if ( "string".equals( typeStr)) {
					paramsArrayList.add( params.getString( paramsIndex));
				}
				else if ( "number".equals( typeStr)) {
					paramsArrayList.add( params.getNumber( paramsIndex));
				}
				else if ( "boolean".equals( typeStr)) {
					paramsArrayList.add( params.getBoolean( paramsIndex));
				}
				else {
					paramsArrayList.add( params.getObject( paramsIndex));
				}
			} // for
		}
		
		thisLoggerWrap.entering( sourceMethod, paramsArrayList.toArray());
	}
	public native JavaScriptObject getEnteringFunction() throws JavaScriptException /*-{
		var jsniLoggerWrapImpl = this;
		var enteringFunction 
		= function( sourceMethod, params) {
			if ( typeof( sourceMethod) != "string") return;
			var paramArray = params;
			if (( params == null) || ( typeof( params) == "undefined")) {
			// On HtmlUnit, accessing params.constructor (i.e. typeof( params.constructor)) looses control when params is null  
				paramArray = new Array();
			}
			else {
				if ( params.constructor) {
					if ( Array != params.constructor) {
						paramArray = new Array( params);
					} 
				}
				else { // params == null
					paramArray = new Array();
				}
			}
			jsniLoggerWrapImpl.@com.newmainsoftech.gwetons.client.logging.JsniLoggerWrapImpl::entering(Ljava/lang/String;Lcom/google/gwt/core/client/JsArrayMixed;)(
				sourceMethod, paramArray);
		}
		return enteringFunction;
	}-*/;
	// ----------------------------------------------------------------------------------------
	
	// about exiting methods ------------------------------------------------------------------
	public native JavaScriptObject getExitingFunction() /*-{
		var loggerWrap = this.@com.newmainsoftech.gwetons.client.logging.JsniLoggerWrapImpl::getLoggerWrap()();
		var exitingFunction
		= function( sourceMethod) {
			if ( loggerWrap) {
				if ( typeof( sourceMethod) != "string") return;
				
				loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::exiting(Ljava/lang/String;)( 
					sourceMethod);
			}
		}
		return exitingFunction;
	}-*/;
	
	public native JavaScriptObject getExitingWithResultFunction() /*-{
		var loggerWrap = this.@com.newmainsoftech.gwetons.client.logging.JsniLoggerWrapImpl::getLoggerWrap()();
		var exitingWithResultFunction
		= function( sourceMethod, result) {
			if ( loggerWrap) {
				if ( typeof( sourceMethod) != "string") return;
				
				if ( typeof( result) == "string") {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::exiting(Ljava/lang/String;Ljava/lang/Object;)( 
						sourceMethod, String( result));
				}
				else if ( typeof( result) == "boolean") {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::exiting(Ljava/lang/String;Ljava/lang/Object;)( 
						sourceMethod, @java.lang.Boolean::valueOf(Z)( result));
				}
				else if ( typeof( result) == "number") {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::exiting(Ljava/lang/String;Ljava/lang/Object;)( 
						sourceMethod, @java.lang.Double::valueOf(D)( result));
				}
				else if ( typeof( result) == "undefined") {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::exiting(Ljava/lang/String;Ljava/lang/Object;)( 
						sourceMethod, null);
				}
				else {
					loggerWrap.@com.newmainsoftech.gwetons.shared.logging.LoggerWrap::exiting(Ljava/lang/String;Ljava/lang/Object;)( 
						sourceMethod, result);
				}
			}
		}
		return exitingWithResultFunction;
	}-*/;
	// ----------------------------------------------------------------------------------------
	
	// logEntering methods --------------------------------------------------------------------
	@Deprecated
	public void logEntering( JsArrayString jsArrayString) {
		LoggerWrap thisLoggerWrap = getLoggerWrap();
			if ( thisLoggerWrap == null) return;
		
		ArrayList<String> stringArrayList = new ArrayList<String>();
		for( int index = 0; index < jsArrayString.length(); index++) {
			stringArrayList.add( jsArrayString.get( index));
		}// for
		thisLoggerWrap.logEntering( stringArrayList.toArray());
	}
	// ----------------------------------------------------------------------------------------
		
	// logExiting methods ---------------------------------------------------------------------
	@Deprecated
	public void logExiting( JsArrayString jsArrayString) {
		LoggerWrap thisLoggerWrap = getLoggerWrap();
			if ( thisLoggerWrap == null) return;
			
		ArrayList<String> stringArrayList = new ArrayList<String>();
		for( int index = 0; index < jsArrayString.length(); index++) {
			stringArrayList.add( jsArrayString.get( index));
		}// for
		thisLoggerWrap.logExiting( stringArrayList.toArray());
	}
	// ----------------------------------------------------------------------------------------
	
}